package thread4;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//解决办法一，哲学家要进餐时，要么同时拿起两支筷子，要么一支筷子都不拿．
class Philosopher {
    //哲学家编号
    public int id;

    public Philosopher(int id) {
        this.id = id;
    }

    //思考
    public void thinking() throws InterruptedException {
        System.out.println("我是哲学家" + this.id + "号，我正在思考！");
        Thread.sleep(1000);
    }

    //吃饭
    public void eating() throws InterruptedException {
        System.out.println("我是哲学家" + this.id + "号，我正在吃饭！");
        Thread.sleep(1000);
    }

    //拿筷子
    public void takeUp(Chopsticks chopsticksMin, Chopsticks chopsticksMax) throws InterruptedException {
        synchronized (Test4.locker) {
            //先尝试拿小号筷子，失败则进入等待状态，并释放锁
            if (!chopsticksMin.used) {//false能拿，true不能拿别人占用的了所以 是!chopsticksMin.used
                chopsticksMin.used = true;
                if (!chopsticksMax.used) {
                    chopsticksMax.used = true;
                } else {
                    Test4.locker.wait();
                }
            } else {
                Test4.locker.wait();
            }
        }
    }

    //放筷子
    public void putDown(Chopsticks chopsticksMin, Chopsticks chopsticksMax) {
        synchronized (Test4.locker) {
            chopsticksMin.used = false;
            chopsticksMax.used = false;
            System.out.println("我是哲学家" + this.id + "号，我吃完了！");
            Test4.locker.notify();
        }
    }
}

//筷子
class Chopsticks {
    //筷子编号
    public int id;
    //筷子状态
    public boolean used;

    public Chopsticks(int id, boolean used) {
        this.id = id;
        this.used = used;
    }
}

public class Test4 {
    public static Object locker = new Object();

    public static void main(String[] args) {
        Philosopher philosopher1 = new Philosopher(1);
        Philosopher philosopher2 = new Philosopher(2);
        Philosopher philosopher3 = new Philosopher(3);
        Philosopher philosopher4 = new Philosopher(4);
        Philosopher philosopher5 = new Philosopher(5);

        Chopsticks chopsticks1 = new Chopsticks(1, false);
        Chopsticks chopsticks2 = new Chopsticks(2, false);
        Chopsticks chopsticks3 = new Chopsticks(3, false);
        Chopsticks chopsticks4 = new Chopsticks(4, false);
        Chopsticks chopsticks5 = new Chopsticks(5, false);

        ExecutorService pool = Executors.newFixedThreadPool(5);
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    philosopher1.thinking();
                    philosopher1.takeUp(chopsticks1, chopsticks2);
                    philosopher1.eating();
                    philosopher1.putDown(chopsticks1, chopsticks2);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    philosopher2.thinking();
                    philosopher2.takeUp(chopsticks2, chopsticks3);
                    philosopher2.eating();
                    philosopher2.putDown(chopsticks2, chopsticks3);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    philosopher3.thinking();
                    philosopher3.takeUp(chopsticks3, chopsticks4);
                    philosopher3.eating();
                    philosopher3.putDown(chopsticks3, chopsticks4);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    philosopher4.thinking();
                    philosopher4.takeUp(chopsticks4, chopsticks5);
                    philosopher4.eating();
                    philosopher4.putDown(chopsticks4, chopsticks5);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        pool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    philosopher5.thinking();
                    philosopher5.takeUp(chopsticks5, chopsticks1);
                    philosopher5.eating();
                    philosopher5.putDown(chopsticks5, chopsticks1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        pool.shutdown();
    }
}

